home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-08-21 | 16.0 KB | 548 lines | [TEXT/PJMM] |
- UNIT Floating;
-
- INTERFACE
-
- VAR
- bottomFloat, topFloat, topWindow: WindowPtr;
- curActivate, curDeactive: WindowPtr;
-
- drawRgn, windowRgn, dragRgn: RgnHandle;
- wPort: GrafPtr;
- dragRect: Rect;
-
-
- PROCEDURE InitFloat;
- PROCEDURE UpdateTopWindow;
- PROCEDURE UpdateFloats;
- FUNCTION NewFloatingWindow (ResID: Integer; wStorage: Ptr): WindowPtr;
- PROCEDURE MakeFloating (whichWindow: WindowPtr);
- FUNCTION IsFloating (whichWindow: WindowPtr): boolean;
- PROCEDURE CloseTheWindow (whichWindow: windowPtr);
- PROCEDURE DisposeTheWindow (whichWindow: WindowPtr);
- PROCEDURE ShowTheWindow (whichWindow: WindowPtr);
- PROCEDURE HideTheWindow (whichWindow: WindowPtr);
- PROCEDURE ShowFloats;
- PROCEDURE HideFloats;
- FUNCTION CurrentWindow: WindowPtr;
- PROCEDURE SelectTheWindow (whichWindow: WindowPtr);
- PROCEDURE DragTheWindow (whichWindow: WindowPtr; theEvent: EventRecord);
- PROCEDURE CalcWindowVis (whichWindow: WindowPeek);
- PROCEDURE GlobalRgn (VAR changeRgn: RgnHandle);
- PROCEDURE LocalRgn (VAR changeRgn: RgnHandle);
-
-
- IMPLEMENTATION
-
-
- PROCEDURE InitFloat;
- { Initialize all of the internal variables }
- BEGIN
- drawRgn := NewRgn;
- windowRgn := NewRgn;
- dragRgn := NewRgn;
- wPort := GrafPtr(NewPtr(SizeOf(GrafPort)));
- OpenPort(wPort);
-
- topFloat := NIL;
- bottomFloat := NIL;
- topWindow := NIL;
-
- dragRect := screenBits.bounds;
- InsetRect(dragRect, 4, 4);
- END;
-
-
- PROCEDURE UpdateTopWindow;
- BEGIN
- IF bottomFloat <> NIL THEN
- topWindow := WindowPtr(WindowPeek(bottomFloat)^.nextWindow)
- ELSE
- topWindow := FrontWindow;
- END;
-
-
- PROCEDURE UpdateFloats;
- VAR
- theWindow: WindowPeek;
-
- BEGIN
- topFloat := NIL;
- bottomFloat := NIL;
- theWindow := WindowPeek(FrontWindow); { Start with the front window }
- IF theWindow <> NIL THEN
- IF IsFloating(WindowPtr(theWindow)) THEN { Is it a floating window? }
- BEGIN
- topFloat := WindowPtr(theWindow); { Yep, let's start figuring out our list starting with that one }
- WHILE IsFloating(WindowPtr(theWindow)) DO
- BEGIN { Continue updating our bottom pointer until we have found the last window }
- bottomFloat := WindowPtr(theWindow);
- theWindow := theWindow^.nextWindow;
- IF theWindow = NIL THEN
- Exit(UpdateFloats);
- END;
- END;
- END;
-
-
- PROCEDURE MakeFloating (whichWindow: WindowPtr);
- BEGIN
- WindowPeek(whichWindow)^.windowKind := 317; { Mark it as a floating window }
- BringToFront(whichWindow); { Floating window must be in front }
- END;
-
-
- FUNCTION NewFloatingWindow (ResID: Integer; wStorage: Ptr): WindowPtr;
- VAR
- theWindow: WindowPtr;
-
- BEGIN
- theWindow := GetNewWindow(ResID, wStorage, NIL);
-
- BringToFront(theWindow); { Floating window must be in front }
- ShowHide(theWindow, true); { Make sure it is visible }
- IF topFloat = NIL THEN { If topFloat is NIL then this is the }
- bottomFloat := theWindow; { the first floating window to be }
- { made. Since it is the first, it must }
- { also be the last }
- topFloat := theWindow; { Mark it is as the top floating window }
- MakeFloating(theWindow); { And mark it as a floating window }
- NewFloatingWindow := theWindow; { Return reference to theWindow }
- END;
-
-
-
- FUNCTION IsFloating (whichWindow: WindowPtr): Boolean;
- BEGIN
- IsFloating := WindowPeek(whichWindow)^.windowKind = 317;
- END;
-
-
- PROCEDURE CloseTheWindow (whichWindow: WindowPtr);
- VAR
- theWindow: WindowPeek;
-
- BEGIN
- CloseWindow(whichWindow);
-
- { Calculate the next window to hilite. Start with the next window }
- { behind the one you are closing. Continue until you find the first }
- { visable one. }
-
- theWindow := WindowPeek(whichWindow)^.nextWindow;
-
- whichWindow := NIL; { get rid of the window! }
-
- IF theWindow <> NIL THEN
- BEGIN
- WHILE NOT theWindow^.visible DO
- BEGIN
- theWindow := theWindow^.nextWindow;
- IF theWindow = NIL THEN
- Exit(CloseTheWindow);
- END
- END;
-
- { If we got a window (other than 0L) then Hilite it and tell the }
- { toolbox to activate that window }
- IF theWindow <> NIL THEN
- BEGIN
- HiliteWindow(WindowPtr(theWindow), true);
- CurActivate := WindowPtr(theWindow);
- { Since one of the windows that was killed could have been a floating }
- { window. We rebuild that list starting with the frontmost window }
- { and working the way through the list until we find the first }
- { nonfloating window which marks the end of the floats. }
-
- UpdateFloats;
- END
- ELSE { We have no windows left so hide our floats }
- HideFloats;
- UpdateTopWindow;
- END;
-
-
- PROCEDURE DisposeTheWindow (whichWindow: WindowPtr);
- VAR
- theWindow: WindowPeek;
- BEGIN
- DisposeWindow(whichWindow);
- { Calculate the next window to hilite. Start with the next window }
- { behind the one you are closing. Continue until you find the first }
- { visible one. }
- theWindow := WindowPeek(whichWindow)^.nextWindow;
- IF theWindow <> NIL THEN
- WHILE NOT theWindow^.visible DO
- theWindow := theWindow^.nextWindow;
-
- IF theWindow = NIL THEN
- exit(DisposeTheWindow);
-
- { If we got a window (other than 0L) then Hilite it and tell the toolbox to activate it }
- IF theWindow <> NIL THEN
- BEGIN
- HiliteWindow(WindowPtr(theWindow), true);
- CurActivate := WindowPtr(theWindow); { Since one of the windows that was killed }
- { could have been a floating window. We }
- { rebuild that list starting with the }
- { frontmost window and working the way through }
- { the list. }
- END
- ELSE { We have no windows left so hide our floats }
- BEGIN
- HideFloats;
- UpdateTopWindow;
- END;
- END;
-
-
- PROCEDURE HideTheWindow (whichWindow: WindowPtr);
-
- VAR
- theWindow: WindowPeek;
-
- BEGIN
- HideWindow(whichWindow);
- { Start with the next window behind the one we are hiding.}
- { Continue searching until we find a visible one. }
- theWindow := WindowPeek(whichWindow)^.nextWindow;
- WHILE NOT theWindow^.visible DO
- theWindow := theWindow^.nextWindow;
- IF theWindow = NIL THEN
- exit(HideTheWindow);
-
- IF theWindow <> NIL THEN { If we found a window, Hilite it }
- BEGIN
- HiliteWindow(WindowPtr(theWindow), true);
- UpdateFloats;
- END;
- END;
-
-
- PROCEDURE ShowFloats;
- VAR
- theWindow: WindowPeek;
- BEGIN
- IF topFloat <> NIL THEN { Do we have floating windows? }
- theWindow := WindowPeek(topFloat); { Start with the top one }
-
- WHILE theWindow <> WindowPeek(bottomFloat)^.nextWindow DO
- BEGIN
- { Contine until we reach the last floating window }
- { Show the window and move on to the next }
- ShowHide(WindowPtr(theWindow), TRUE);
- theWindow := theWindow^.nextWindow;
- END;
- IF theWindow = NIL THEN
- exit(ShowFloats);
- END;
-
-
- PROCEDURE HideFloats;
- VAR
- theWindow: WindowPeek;
- BEGIN
- IF topFloat <> NIL THEN { Do we have floating windows? }
- theWindow := WindowPeek(topFloat); { Start with the top one }
- WHILE theWindow <> WindowPeek(bottomFloat)^.nextWindow DO
- BEGIN
- { Contine until we reach the }
- { last floating window }
- { Hide the window and move }
- { on to the next }
- ShowHide(WindowPtr(theWindow), false);
- theWindow := theWindow^.nextWindow;
- END;
- IF theWindow = NIL THEN
- exit(HideFloats)
- END;
-
-
- FUNCTION CurrentWindow: WindowPtr;
- BEGIN
- CurrentWindow := topWindow;
- END;
-
-
- PROCEDURE SelectTheWindow (whichWindow: WindowPtr);
- VAR
- floating: Boolean; { Is it a floating window }
- bottomPeek: WindowPeek; { Reference to bottom float }
- theWindowPeek: WindowPeek; { Generic reference to window }
- lastTop: WindowPtr; { The last top window }
- beforePeek: WindowPeek; { The location of where the the window will be moved }
- savePort: GrafPtr;
-
- BEGIN
- floating := IsFloating(whichWindow); { Is it a floating window? }
- IF floating THEN
- BEGIN
- IF whichWindow <> topFloat THEN
- BEGIN { If it is not the front floating window, bring it to the front }
- BringToFront(whichWindow);
- topFloat := whichWindow;
-
- { and find the last floating window }
- theWindowPeek := WindowPeek(whichWindow);
- WHILE IsFloating(WindowPtr(theWindowPeek)) DO
- BEGIN
- bottomFloat := WindowPtr(theWindowPeek);
- theWindowPeek := theWindowPeek^.nextWindow;
- END
- END
- END
- ELSE
- BEGIN
- IF bottomFloat = NIL THEN { if there are no other floating windows }
- BEGIN { just bring it to the front. }
- IF whichWindow <> FrontWindow THEN
- SelectWindow(whichWindow);
- END
- ELSE
- BEGIN
- bottomPeek := WindowPeek(bottomFloat);
- theWindowPeek := WindowPeek(whichWindow);
-
- IF theWindowPeek <> bottomPeek^.nextWindow THEN
- BEGIN
- { It's not the top document window, now we find what that is }
- lastTop := WindowPtr(bottomPeek^.nextWindow);
-
- { Create deactivate event for last active document window }
- CurDeactive := lastTop;
- HiliteWindow(lastTop, false);
-
- { Now we rewrite the window list to change the location }
- { of the window. First we find the window that was before }
- { the window we want to move. We then set its nextWindow }
- { field to the window in front of the window we are moving. }
- { That then removes the window from the window list. }
- { Now we want to place it rigth after the bottommost }
- { floating window. To do that, we set the nextWindow }
- { field of the window we are moving to the window right }
- { after the bottommost floating window and set the nextWindow }
- { field of the bottommost floating window to the window }
- { we are moving. Confusing eh? }
-
- beforePeek := bottomPeek^.nextWindow;
- WHILE beforePeek^.nextWindow <> theWindowPeek DO
- beforePeek := beforePeek^.nextWindow;
- beforePeek^.nextWindow := theWindowPeek^.nextWindow;
-
- theWindowPeek^.nextWindow := bottomPeek^.nextWindow;
- bottomPeek^.nextWindow := theWindowPeek;
-
- { Now we have to recalculate all the visible regions }
- { and redraw newly exposed areas }
-
- GetPort(savePort);
- SetPort(whichWindow);
-
- { We start with the visible region of our window but }
- { unfortunately, it is in local coordinates of the }
- { window so we convert it to global by using the GlobalRgn }
- { procedure }
-
- CopyRgn(whichWindow^.visRgn, drawRgn);
- GlobalRgn(drawRgn);
-
- { We then subtract the visible region of the window }
- { from the windows structure region. This gives us }
- { the area which is being brought to the front }
-
- DiffRgn(theWindowPeek^.strucRgn, drawRgn, drawRgn);
-
- { Paint the area and hilite it to show it is now active }
- PaintOne(WindowPeek(whichWindow), drawRgn);
- HiliteWindow(whichWindow, true);
-
- { PaintOne sets thePort to the Window Manager Port so }
- { we must reset thePort to whichWindow. We then call }
- { CalcWindowVis which will recalculate all the visible }
- { regions }
-
- SetPort(whichWindow);
- CalcWindowVis(theWindowPeek);
-
- { Then invalidate the region so that it will update properly }
- InvalRgn(drawRgn);
- SetPort(savePort);
-
- { And finally, generate another event to activate the new window }
- CurActivate := whichWindow;
- END
- END
- END;
- IF NOT WindowPeek(whichWindow)^.visible THEN { A little kludge }
- { has been added for floating window support }
- { which makes sure to make the window visible }
- { if it is hidden }
- ShowHide(whichWindow, true);
-
- UpdateTopWindow; { Rebuild our window list }
- END;
-
-
-
- PROCEDURE DragTheWindow (whichWindow: WindowPtr; theEvent: EventRecord);
- VAR
- savePort: GrafPtr; { Saved graphics pointer }
- thePoint: Point; { Used to remember the original }
- { location of the window }
- newLoc: LongInt; { Window's new position }
- hDelta, vDelta: Integer; { How much to move the window }
- theWindow: WindowPeek;
-
- BEGIN
-
- { Since dragging a window automatically brings it to the front }
- { unless you are holding the command key down, this routine needs }
- { to be redone. Otherwise it would kill the floating window }
- { relationship. }
-
- { If it's a floating window and not the front floating window and }
- { the command key is not down, bring it to the front before dragging }
-
- IF IsFloating(whichWindow) THEN
- BEGIN
- IF (whichWindow <> topFloat) & NOT (BAND(theEvent.modifiers, cmdKey) = cmdKey) THEN
- SelectTheWindow(whichWindow);
- END
- { if the window is not the front document window and the command }
- { key is not down, select the window before dragging }
-
- ELSE IF topFloat = NIL THEN
- BEGIN
- IF (whichWindow <> FrontWindow) & NOT (BAND(theEvent.modifiers, cmdKey) = cmdKey) THEN
- BEGIN
- SelectWindow(whichWindow);
- END
- END
- ELSE IF (whichWindow <> WindowPtr(WindowPeek(bottomFloat)^.nextWindow)) & NOT (BAND(theEvent.modifiers, cmdKey) = cmdKey) THEN
- BEGIN
- SelectTheWindow(whichWindow);
- END;
-
- IF NOT StillDown THEN
- Exit(DragTheWindow);
-
- GetPort(savePort);
- SetPort(whichWindow);
-
- { remember the top-left coordinate of the window }
- thePoint := whichWindow^.portRect.topLeft;
- LocalToGlobal(thePoint);
-
- { Copy the window's structure region to be used for dragging }
- CopyRgn(WindowPeek(whichWindow)^.strucRgn, dragRgn);
-
- { Use our graphics port }
- SetPort(wPort);
-
- { We must figure out the drag region for the window. }
- { Start with the top window and work or way through the window }
- { list altering our graphics port to the screen's visible region. }
- { This effectively gives us a visible region of the screen minus }
- { that of all windows above the window we are dragging }
-
- CopyRgn(GetGrayRgn, wPort^.visRgn);
-
- theWindow := WindowPeek(FrontWindow);
- IF theWindow <> WindowPeek(whichWindow) THEN
- BEGIN
- DiffRgn(wPort^.visRgn, theWindow^.strucRgn, wPort^.visRgn);
- WHILE theWindow <> WindowPeek(whichWindow) DO
- BEGIN
- DiffRgn(wPort^.visRgn, theWindow^.strucRgn, wPort^.visRgn);
- theWindow := theWindow^.nextWindow;
- END;
- END;
-
- { drag the window }
- newLoc := DragGrayRgn(dragRgn, theEvent.where, dragRect, dragRect, noConstraint, NIL);
- IF newLoc <> $80008000 THEN
- BEGIN
- hDelta := LoWord(newLoc);
- vDelta := HiWord(newLoc);
- MoveWindow(whichWindow, hDelta + thePoint.h, vDelta + thePoint.v, false);
- END;
- SetPort(savePort);
- END;
-
-
-
- PROCEDURE CalcWindowVis (whichWindow: WindowPeek);
- VAR
- theWindow: WindowPeek;
- savePort: GrafPtr;
-
- BEGIN
- GetPort(savePort);
-
- { First we start with an empty region. From there we begin with }
- { the front window which would be one of the floating windows }
- { and add its structure region to windowRgn. We continue to add }
- { in the regions until we reach whichWindow }
-
- SetEmptyRgn(windowRgn);
- theWindow := WindowPeek(FrontWindow);
- WHILE theWindow <> whichWindow DO
- BEGIN
- UnionRgn(windowRgn, theWindow^.strucRgn, windowRgn);
- theWindow := theWindow^.nextWindow;
- END;
-
- { We now have all the regions of all the windows in front of whichWindow. }
- { To calculate the visible region of whichWindow, we copy its content region }
- { (which is in global coordinates) into the visRgn field. }
- { We then SUBTRACT the region we generated before from the visible region }
- { of the window. Finally, convert it into local coordinates for the toolbox }
-
- SetPort(WindowPtr(whichWindow));
- CopyRgn(whichWindow^.contRgn, whichWindow^.port.visRgn);
- DiffRgn(whichWindow^.port.visRgn, windowRgn, whichWindow^.port.visRgn);
- LocalRgn(whichWindow^.port.visRgn);
-
- { Now we have to calculate all the visible regions for all windows behind }
- { whichWindow. We just go through the same process again and again, }
- { but each time we add the window's structure region into windowRgn to subtract again. }
-
- theWindow := whichWindow;
- WHILE theWindow^.nextWindow <> NIL DO
- BEGIN
- UnionRgn(windowRgn, theWindow^.strucRgn, windowRgn);
- theWindow := theWindow^.nextWindow;
- SetPort(WindowPtr(theWindow));
- CopyRgn(theWindow^.contRgn, theWindow^.port.visRgn);
- DiffRgn(theWindow^.port.visRgn, windowRgn, theWindow^.port.visRgn);
- LocalRgn(theWindow^.port.visRgn)
- END;
- SetPort(savePort);
- END;
-
-
- PROCEDURE GlobalRgn (VAR changeRgn: RgnHandle);
- { Converts a region into Global Coordinates }
- VAR
- theRect: Rect;
- BEGIN
- theRect := thePort^.portBits.bounds;
- OffsetRgn(changeRgn, -theRect.left, -theRect.top);
-
- END;
-
-
- PROCEDURE LocalRgn (VAR changeRgn: RgnHandle);
- { Converts a region into Global Coordinates }
- VAR
- theRect: Rect;
-
- BEGIN
- theRect := thePort^.portBits.bounds;
- OffsetRgn(changeRgn, theRect.left, theRect.top);
- END;
-
-
- END.
-
-
-